import axios from 'axios';
import { Message } from 'element-ui';
import store from '../store';
import router from '../router';

export default class HttpRequest {
  constructor(baseUrl) {
    this.baseUrl = baseUrl || '/';
    this.axiosPromiseQueue = [];
    // 不需要 token 的接口地址
    this.withoutHeaderApi = ['/risk-sys/login'];
    // 白名单
    this.whiteListOfCancelApi = [
      '/screen/*',  // 以 /screen/ 开头的接口直接跳过重复请求的拦截
      '/risk-sys-dictionary/*', // 以 /risk-sys-dictionary/ 开头的接口直接跳过重复请求的拦截
      '/common-controller/uploadFile',  // 文件上传跳过重复请求拦截
    ];
  }

  getBaseConfig(url) {
    const headers = {
      'Content-Type': 'application/json',
    };

    if (!this.withoutHeaderApi.includes(url)) {
      const currentUser = store.getters['user/user'];
      if (currentUser && currentUser['token']) {
        headers['Authorization'] = currentUser.token;
      }
    }

    return {
      headers,
      baseURL: this.baseUrl,
      timeout: 5000,
    };
  }

  /**
   * 将请求队列中已完成的请求销毁移除
   * @param config
   */
  destroy(config) {
    const findResponseIndex = this.axiosPromiseQueue.findIndex(d => d.url === config.url && d.method === config.method);
    if (findResponseIndex > -1) {
      this.axiosPromiseQueue.splice(findResponseIndex, 1);
    }

    if (!this.axiosPromiseQueue.length) {
      // console.log('loading hide.');
    }
  }

  /**
   * 删除 pending 状态中的请求
   * @param config
   */
  removePending(config) {
    [...this.axiosPromiseQueue].forEach((item, idx) => {
      if (item.url === config.url && item.method === config.method) {
        item.cancel(`[${item.method} ${item.url}] 重复请求取消.`);
        this.axiosPromiseQueue.splice(idx, 1);
      }
    });
  }

  /**
   * 清除所有请求
   */
  clearAllRequest() {
    if (this.axiosPromiseQueue.length > 0) {
      this.axiosPromiseQueue.forEach(e => e.cancel(`[${e.method} ${e.url}] 请求取消.`));
      this.axiosPromiseQueue = [];
    }
  }

  /**
   * 拦截器
   * @param instance
   */
  interceptors(instance) {
    instance.interceptors.request.use(config => {
      // 处理IE的缓存问题
      if (config && config.params) {
        config.params.loadCurrent = new Date().getTime();
      } else if (config) {
        config.params = { loadCurrent: new Date().getTime() };
      }

      const isSkip = this.whiteListOfCancelApi.some(item => {
        if (item.indexOf('/*') > -1) {
          return config.url.startsWith(item.split('/*')[0]);
        }
        return item === config.url;
      });
      if (isSkip) return config;

      // 发起请求时，取消当前重复请求的接口
      this.removePending(config);

      config.cancelToken = new axios.CancelToken(cancel => {
        this.axiosPromiseQueue.push({
          cancel,
          url: config.url,
          method: config.method,
        });
      });

      if (this.axiosPromiseQueue.length > 0) {
        // console.log('loading show.');
      }

      return config;
    }, error => Promise.reject(error));

    instance.interceptors.response.use(res => {
      this.destroy(res.config);

      if (res.status === 200) {
        // 文件下载直接返回 response 对象
        if (res.config.responseType && ['blob', 'arraybuffer'].includes(res.config.responseType.toLocaleLowerCase())) {
          return Promise.resolve(res);
        }

        const data = res.data;
        if (data) {
          // 如果返回的数据结构中没有code,则默认为直接返回数据
          if (!data.code) {
            return Promise.resolve(data);
          }

          switch (data.code) {
            case '200':
              return Promise.resolve(data.result);
            case '403':
            case '408':
              router.push('/login');
              break;
            // token 过期
            case '507':
              store.dispatch('resetGlobalState', null, { root: true });
              router.push({ path: '/login' });
              break;
            case '3004':
            case '3005':
            case '7003':
              Message.error('角色已被禁用，无法登录系统');
              break;
            default:
              Message.error(data.message);
              break;
          }
        }
      }

      return Promise.reject(res);
    }, err => {
      if (axios.isCancel(err)) {
        // eslint-disable-next-line no-console
        console.log('Request canceled: ', err.message);
        return new Promise(() => {});
      }

      if (err.response) {
        switch (err.response.status) {
          case 401:
            this.clearAllRequest();
            // 401 清除token信息并跳转到登录页面
            store.commit('user/SET_CURRENT_USER', null);

            // 只有在当前路由不是登录页面才跳转
            router.currentRoute.name !== 'login' && router.replace({ path: 'login', query: { redirect: router.currentRoute.path } });
            return Promise.resolve(false);
          default:
            break;
        }
      }
      return Promise.reject(err.response.data);
    });
  }

  request(options) {
    const instance = axios.create();
    this.interceptors(instance);
    const baseConfig = this.getBaseConfig(options.url);
    if (options.headers) {
      baseConfig.headers = { ...baseConfig.headers, ...options.headers };
      delete options.headers;
    }
    return instance(Object.assign(baseConfig, options));
  }
}
